package com.sunxd.zookeeper.controller;

import com.alibaba.fastjson.JSON;
import com.sunxd.zookeeper.use.ZkConf;
import com.sunxd.zookeeper.use.ZkMyselfUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.data.Stat;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * zk 的 连接watch  业务节点的监听 业务数据的回掉测试集合
 *
 * 其中watch 和 data callback可单独放在类里面，此处简便测试
 * @author: 作者名称
 * @date: 2021-06-28 03:11
 **/
@RestController
@RequestMapping("myself")
@RequiredArgsConstructor
@Slf4j
public class MySelfController {

    private final ZkMyselfUtil zkMyselfUtil;
    private final ZkConf zkConf;



    @RequestMapping("createPNode")
    public String createPNode(@RequestParam String path, @RequestParam String data) {
        zkMyselfUtil.setZooKeeper(zkConf.getZookeeper());
        // 创建永久节点
        return zkMyselfUtil.createP(path, data);
    }

    @RequestMapping("getDataWithTrueWatch")
    public String getDataWithTrueWatch(@RequestParam String path,@RequestParam String data) throws InterruptedException {
        zkMyselfUtil.setZooKeeper(zkConf.getZookeeper());
        // 获取数据并走默认的watcher
        String result = zkMyselfUtil.getData(path, Boolean.TRUE);
        Thread.sleep(1000L);
        zkMyselfUtil.setData(path,data);
        Thread.sleep(5000L);
        return result;
    }

    @RequestMapping("getDataWithFalseWatch")
    public String getDataWithFalseWatch(@RequestParam String path,@RequestParam String data) throws InterruptedException{
        zkMyselfUtil.setZooKeeper(zkConf.getZookeeper());
        // 获取数据不走默认的监听器
        String result = zkMyselfUtil.getData(path, Boolean.FALSE);
        Thread.sleep(1000L);
        zkMyselfUtil.setData(path,data);
        Thread.sleep(5000L);
        return result;
    }


    /**
     *  测试 节点变更监听的回掉
     *  每次watch只会触发一次，如果需要继续监听，在在watch里在执行zkMyselfUtil.getDataWithWatcher（。。。watch->this）
     * @param path
     * @param data
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("getDataWithWatcher")
    public String getDataWithWatcher(@RequestParam String path,@RequestParam String data) throws InterruptedException{
        zkMyselfUtil.setZooKeeper(zkConf.getZookeeper());
        // 获取数据不走默认的监听器
        String result = zkMyselfUtil.getDataWithWatcher(path, watchedEvent -> {
//            watchedEvent.getPath(); 获取路径
            log.info(" controller watchedEvent data:{}", JSON.toJSONString(watchedEvent));
            switch (watchedEvent.getState()) {
                case Disconnected:
                    log.info("---[ zk 连接状态 -> Disconnected  ]------------------");
                    break;
                case SyncConnected:
                    log.info("---[ zk 连接状态 -> SyncConnected  ]------------------");
                    break;
                case AuthFailed:
                    log.info("---[ zk 连接状态 -> AuthFailed  ]------------------");
                    break;
                case ConnectedReadOnly:
                    log.info("---[ zk 连接状态 -> ConnectedReadOnly  ]------------------");
                    break;
                case SaslAuthenticated:
                    log.info("---[ zk 连接状态 -> SaslAuthenticated  ]------------------");
                    break;
                case Expired:
                    log.info("---[ zk 连接状态 -> Expired  ]------------------");
                    break;
                case Closed:
                    log.info("---[ zk 连接状态 -> Closed  ]------------------");
                    break;
            }
            switch (watchedEvent.getType()) {
                case None:
                    log.info("---[ zk 节点变化 -> None:  ]------------------");
                    break;
                case NodeCreated:
                    log.info("---[ zk 节点变化 -> NodeCreated:  ]------------------");
                    break;
                case NodeDeleted:
                    log.info("---[ zk 节点变化 -> NodeDeleted:  ]------------------");
                    break;
                case NodeDataChanged:
                    log.info("---[ zk 节点变化 -> NodeDataChanged:  ]------------------");
                    break;
                case NodeChildrenChanged:
                    log.info("---[ zk 节点变化 -> NodeChildrenChanged:  ]------------------");
                    break;
                case DataWatchRemoved:
                    log.info("---[ zk 节点变化 -> DataWatchRemoved:  ]------------------");
                    break;
                case ChildWatchRemoved:
                    log.info("---[ zk 节点变化 -> ChildWatchRemoved:  ]------------------");
                    break;
                case PersistentWatchRemoved:
                    log.info("---[ zk 节点变化 -> PersistentWatchRemoved:  ]------------------");
                    break;
            }
        });
        Thread.sleep(1000L);
//      1. SyncConnected  并触发  NodeDataChanged
//        Stat stat = zkMyselfUtil.setData(path,data);

//      2.  SyncConnected  并触发  NodeDeleted
// ** //        zkMyselfUtil.delete(path);
        Thread.sleep(5000L);
        return result;
    }


    /**
     *  获取数据走了异步-
     *  watch 设置为false 没有走监听
     * @param path path
     * @param data
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("getDataWithDataCallbackAndAndFalseWatch")
    public void getDataWithDataCallbackAndAndFalseWatch(@RequestParam String path,@RequestParam String data) throws InterruptedException {
        zkMyselfUtil.setZooKeeper(zkConf.getZookeeper());
        zkMyselfUtil.getDataWithDataCallbackAndBWatch(path,Boolean.FALSE, new AsyncCallback.DataCallback() {

            @Override
            public void processResult(int i, String path, Object ctx, byte[] bytes, Stat stat) {
                log.info("++++getdatawithdatacallbackandbwatch 获取数据回掉  KeeperException.Code 操作状态吗 i:{}, path:{}, ctx:{}, bytes:{}, stat:{}",i,path,JSON.toJSONString(ctx),new String(bytes),JSON.toJSONString(stat));
            }
        },path);
        Thread.sleep(5000L);
    }

    /**
     *  测试 节点变更监听的回掉
     *  每次watch只会触发一次，如果需要继续监听，在在watch里在执行zkMyselfUtil.getDataWithWatcher（。。。watch->this）
     * @param path path
     * @param data
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("getDataWithDataCallbackAndAndTrueWatch")
    public void getDataWithDataCallbackAndAndTrueWatch(@RequestParam String path,@RequestParam String data) throws InterruptedException {
        zkMyselfUtil.setZooKeeper(zkConf.getZookeeper());
        zkMyselfUtil.getDataWithDataCallbackAndBWatch(path,Boolean.TRUE, new AsyncCallback.DataCallback() {

            @Override
            public void processResult(int i, String path, Object ctx, byte[] bytes, Stat stat) {
                log.info("++++getdatawithdatacallbackandbwatch 获取数据回掉  KeeperException.Code 操作状态吗 i:{}, path:{}, ctx:{}, bytes:{}, stat:{}",i,path,JSON.toJSONString(ctx),new String(bytes),JSON.toJSONString(stat));
            }
        },path);

        Thread.sleep(2000L);
        zkMyselfUtil.setData(path,data);
        Thread.sleep(5000L);
    }

    /**
     *  测试 节点变更监听的回掉
     *  每次watch只会触发一次，如果需要继续监听，在在watch里在执行zkMyselfUtil.getDataWithWatcher（。。。watch->this）
     * @param path path
     * @param data
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("getDataWithDataCallbackAndAndWatch")
    public void getDataWithDataCallbackAndAndWatch(@RequestParam String path,@RequestParam String data) throws InterruptedException {
        zkMyselfUtil.setZooKeeper(zkConf.getZookeeper());
        zkMyselfUtil.getDataWithDataCallbackWatch(path, new Watcher() {
            @Override
            public void process(WatchedEvent watchedEvent) {
                switch (watchedEvent.getType()) {
                    case None:
                        log.info("---[ zk 节点变化 -> None:  ]------------------");
                        break;
                    case NodeCreated:
                        log.info("---[ zk 节点变化 -> NodeCreated:  ]------------------");
                        break;
                    case NodeDeleted:
                        log.info("---[ zk 节点变化 -> NodeDeleted:  ]------------------");
                        break;
                    case NodeDataChanged:
                        zkMyselfUtil.getDataWithDataCallbackWatch(path,this,new AsyncCallback.DataCallback() {
                            @Override
                            public void processResult(int i, String path, Object ctx, byte[] bytes, Stat stat) {
                                log.info("++++getdatawithdatacallbackandbwatch 获取数据回掉  KeeperException.Code 操作状态吗 i:{}, path:{}, ctx:{}, bytes:{}, stat:{}",i,path,JSON.toJSONString(ctx),new String(bytes),JSON.toJSONString(stat));
                            }
                        },path);
                        log.info("---[ zk 节点变化 -> NodeDataChanged:  ]------------------");
                        break;
                    case NodeChildrenChanged:
                        log.info("---[ zk 节点变化 -> NodeChildrenChanged:  ]------------------");
                        break;
                    case DataWatchRemoved:
                        log.info("---[ zk 节点变化 -> DataWatchRemoved:  ]------------------");
                        break;
                    case ChildWatchRemoved:
                        log.info("---[ zk 节点变化 -> ChildWatchRemoved:  ]------------------");
                        break;
                    case PersistentWatchRemoved:
                        log.info("---[ zk 节点变化 -> PersistentWatchRemoved:  ]------------------");
                        break;
                }

            }
        }, new AsyncCallback.DataCallback() {

            @Override
            public void processResult(int i, String path, Object ctx, byte[] bytes, Stat stat) {
                log.info("++++getdatawithdatacallbackandbwatch 获取数据回掉  KeeperException.Code 操作状态吗 i:{}, path:{}, ctx:{}, bytes:{}, stat:{}",i,path,JSON.toJSONString(ctx),new String(bytes),JSON.toJSONString(stat));
            }
        },path);

        Thread.sleep(2000L);
        zkMyselfUtil.setData(path,data);
        log.info("第一个变更。。。等待回掉。。。。。。");
        Thread.sleep(2000L);
        zkMyselfUtil.setData(path,data);
        log.info("第二 个变更。。。等待回掉。。。。。。");
        zkMyselfUtil.delete(path);
        log.info("第三个删除 。。。等待回掉。。。。。。");
        Thread.sleep(50000L);
    }




}
